package com.study.cn.entity;

import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Author: lss
 * @Date: 2022/1/18 16:57
 */
@Data
public class DemoReflect01 {

    @Excel(name = "id")
    private Integer id;

    @Excel(name = "姓名")
    private String name;

    @Excel(name = "日期")
    private String date;

    @Excel(name = "地址")
    private String site;

    @Excel(name = "是否启用")
    private String isFlag;

    /**
     * 有一个很大的缺陷需调整，在赋值的参数类型上无法达到统一，需要做设计
     * @param args
     */
    @SneakyThrows
    public static void main(String[] args) {
        DemoReflect01 demoReflect01 = new DemoReflect01();
        // 获取参数
        Map<String, Object> map = demoReflect01.getMap();
        Set<String> keySet = map.keySet();
        Class<? extends DemoReflect01> aClass = demoReflect01.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            String typeName = field.getGenericType().getTypeName();
            /**
             * 这里是用excel注解的name来区分的，视情况而定，也可以用属性名来判断
             */
            Excel excel = field.getAnnotation(Excel.class); // 获取属性上的注解对象
            String excelName = excel.name();
            if (keySet.contains(excelName)){
                String value = String.valueOf(map.get(excelName)); // 值
                if (name == "id"){
                    field.set(demoReflect01,Integer.valueOf(value));
                }else {
                    field.set(demoReflect01,value);
                }
            }
        }
        System.out.println("根据传入的参数赋值:"+demoReflect01);
    }

    public Map<String,Object> getMap(){
        Map<String,Object> map = new HashMap<>();
        map.put("id",1);
        map.put("姓名","lss");
        map.put("日期","2020-07-01");
        map.put("地址","湖北");
        map.put("是否启用","否");
        return map;
    }
    static class DemoReflectTest{
        /**
         * 针对上面的一个测试的问题做出了优化
         * @param args
         */
        public static void main(String[] args) throws IllegalAccessException {
            DemoReflect01 demoReflect01 = new DemoReflect01();
            // 获取参数
            Map<String, Object> map = demoReflect01.getMap();
            Set<String> keySet = map.keySet();
            Class<? extends DemoReflect01> aClass = demoReflect01.getClass();
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
                // 访问私有变量授权，在其他类里面必须设置为true
                field.setAccessible(true);
                String name = field.getName();
                String typeName = field.getGenericType().getTypeName();
                /**
                 * 这里是用excel注解的name来区分的，视情况而定，也可以用属性名来判断
                 */
                Excel excel = field.getAnnotation(Excel.class); // 获取属性上的注解对象
                String excelName = excel.name();
                if (keySet.contains(excelName)){
                    String value = String.valueOf(map.get(excelName)); // 值
                    // 这里针对我们所获取的值做出改变
                    Object o = typeChange(value, typeName);
                    field.set(demoReflect01,o);
                }
            }
            System.out.println("根据传入的参数赋值:"+demoReflect01);
        }

        /**
         * 利用泛型改变值的属性类型，避免出现属性值赋值异常
         * @param o
         * @param classZZ
         * @param <T>
         * @return
         */
        public static <T>T typeChange(Object o,String classZZ){
            T t = (T) o;
            if(!ObjectUtils.isEmpty(classZZ)){
                if (classZZ.contains("String")){
                    String str = String.valueOf(o);
                    t = (T)str;
                }else if (classZZ.contains("Integer")){
                    Integer integer = Integer.valueOf(o.toString());
                    t = (T) integer;
                }else if (classZZ.contains("Double")){
                    Double aDouble = Double.valueOf(o.toString());
                    t = (T) aDouble;
                }else {
                    t = (T)o;
                }
            }
            return t;
        }
    }
}
